home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / i_l / irit5 / cagd_lib / cagd_arc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-31  |  11.9 KB  |  277 lines

  1. /******************************************************************************
  2. * Cagd_Arc.c - Curve representation of arcs and circles                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Jun. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "cagd_loc.h"
  11.  
  12. #define UNIT_CIRCLE_ORDER 3                /* Quadratic rational curve. */
  13. #define UNIT_CIRCLE_LENGTH 9      /* Nine control points in the unit circle. */
  14. #define UNIT_PCIRCLE_ORDER 4              /* Cubic polynomial curve. */
  15. #define UNIT_PCIRCLE_LENGTH 13           /* control points in the unit circle. */
  16.  
  17. static int
  18.     UnitCircleKnots[UNIT_CIRCLE_ORDER + UNIT_CIRCLE_LENGTH] =
  19.                     { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4 };
  20. static int
  21.     UnitCircleX[UNIT_CIRCLE_LENGTH] = { 1, 1, 0, -1, -1, -1, 0, 1, 1 };
  22. static int
  23.     UnitCircleY[UNIT_CIRCLE_LENGTH] = { 0, 1, 1, 1, 0, -1, -1, -1, 0 };
  24.  
  25. static int
  26.     UnitPCircleKnots[UNIT_PCIRCLE_ORDER + UNIT_PCIRCLE_LENGTH] =
  27.              { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
  28.  
  29. static CagdRType
  30.     PolyApproxRotAngles[] = {
  31.     0,
  32.     33.523898, /* arcsin(4 (sqrt(2) - 1) / 3) */
  33.     90 - 33.523898,
  34.     90
  35.     };
  36.  
  37. /*****************************************************************************
  38. * DESCRIPTION:                                                               M
  39. * Creates an arc at the specified position as a rational quadratic Bezier    M
  40. * curve.                                     M
  41. *   The arc is assumed to be less than 180 degrees from Start to End in the  M
  42. * shorter path as arc where Center as arc center.                 M
  43. *                                                                            *
  44. * PARAMETERS:                                                                M
  45. *   Start:       Point of beginning of arc.                                  M
  46. *   Center:      Point of arc.                                               M
  47. *   End:         Point of end of arc.                                          M
  48. *                                                                            *
  49. * RETURN VALUE:                                                              M
  50. *   CagdCrvStruct *: A rational quadratic Bezier curve representing the arc. M
  51. *                                                                            *
  52. * KEYWORDS:                                                                  M
  53. *   BzrCrvCreateArc, circle, arc                                             M
  54. *****************************************************************************/
  55. CagdCrvStruct *BzrCrvCreateArc(CagdPtStruct *Start,
  56.                    CagdPtStruct *Center,
  57.                    CagdPtStruct *End)
  58. {
  59.     int i;
  60.     CagdCrvStruct
  61.     *Arc = BzrCrvNew(3, CAGD_PT_P3_TYPE);
  62.     CagdRType Len, CosAlpha, Radius,
  63.     **Points = Arc -> Points;
  64.     CagdVecStruct V1, V2, V;
  65.  
  66.     /* Copy first point. */
  67.     Points[X][0] = Start -> Pt[0];
  68.     Points[Y][0] = Start -> Pt[1];
  69.     Points[Z][0] = Start -> Pt[2];
  70.     Points[W][0] = 1.0;
  71.  
  72.     /* Copy last point. */
  73.     Points[X][2] = End -> Pt[0];
  74.     Points[Y][2] = End -> Pt[1];
  75.     Points[Z][2] = End -> Pt[2];
  76.     Points[W][2] = 1.0;
  77.  
  78.     /* Compute position of middle point. */
  79.     Len = 0.0;
  80.     for (i = 0; i < 3; i++) {
  81.     V1.Vec[i] = Start -> Pt[i] - Center -> Pt[i];
  82.     V2.Vec[i] = End -> Pt[i] - Center -> Pt[i];
  83.     V.Vec[i] = V1.Vec[i] + V2.Vec[i];
  84.     Len += SQR(V.Vec[i]);
  85.     }
  86.  
  87.     if (APX_EQ(Len, 0.0)) {
  88.     CagdCrvFree(Arc);
  89.     CAGD_FATAL_ERROR(CAGD_ERR_180_ARC);
  90.     return NULL;
  91.     }
  92.     else
  93.     Len = sqrt(Len);
  94.  
  95.     for (i = 0; i < 3; i++)
  96.     V.Vec[i] /= Len;
  97.  
  98.     /* Compute cosine alpha (where alpha is the angle between V and V1. */
  99.     Radius = sqrt(DOT_PROD(V1.Vec, V1.Vec));
  100.     CosAlpha = DOT_PROD(V1.Vec, V.Vec) / Radius;
  101.  
  102.     CAGD_DIV_VECTOR(V, CosAlpha);
  103.     CAGD_MULT_VECTOR(V, Radius);
  104.  
  105.     /* And finally fill in the middle point with CosAlpha as the Weight. */
  106.     Points[X][1] = (Center -> Pt[0] + V.Vec[0]) * CosAlpha;
  107.     Points[Y][1] = (Center -> Pt[1] + V.Vec[1]) * CosAlpha;
  108.     Points[Z][1] = (Center -> Pt[2] + V.Vec[2]) * CosAlpha;
  109.     Points[W][1] = CosAlpha;
  110.  
  111.     return Arc;
  112. }
  113.  
  114. /******************************************************************************
  115. * DESCRIPTION:                                                               M
  116. * Creates a circle at the specified position as a rational quadratic Bspline M
  117. * curve.                                      M
  118. *   Constructs a unit circle as 4 90 degrees arcs of rational quadratic      M
  119. * Bezier segments using a predefined constants.                     M
  120. *                                                                            *
  121. * PARAMETERS:                                                                M
  122. *   None                                                                     M
  123. *                                                                            *
  124. * RETURN VALUE:                                                              M
  125. *   CagdCrvStruct *: A rational quadratic bsplinecurve representing a unit   M
  126. *                    circle.                                                 M
  127. *                                                                            *
  128. * KEYWORDS:                                                                  M
  129. *   BspCrvCreateUnitCircle, circle                                           M
  130. *****************************************************************************/
  131. CagdCrvStruct *BspCrvCreateUnitCircle(void)
  132. {
  133.     int i;
  134.     CagdRType Weight,
  135.         W45 = sin(M_PI / 4.0);
  136.     CagdCrvStruct
  137.     *Circle = BspCrvNew(UNIT_CIRCLE_LENGTH, UNIT_CIRCLE_ORDER,
  138.                                   CAGD_PT_P3_TYPE);
  139.     CagdRType
  140.     **Points = Circle -> Points;
  141.  
  142.     for (i = 0; i < UNIT_CIRCLE_LENGTH + UNIT_CIRCLE_ORDER; i++)
  143.     Circle -> KnotVector[i] = UnitCircleKnots[i];
  144.  
  145.     for (i = 0; i < UNIT_CIRCLE_LENGTH; i++) {
  146.     Weight = Points[W][i] = i % 2 ? W45: 1.0;
  147.     Points[X][i] = UnitCircleX[i] * Weight;
  148.     Points[Y][i] = UnitCircleY[i] * Weight;
  149.     Points[Z][i] = 0.0;
  150.     }
  151.  
  152.     return Circle;
  153. }
  154.  
  155. /*****************************************************************************
  156. * DESCRIPTION:                                                               M
  157. * Creates a circle at the specified position as a rational quadratic Bspline M
  158. * curve. Circle is always paralell to the XY plane.                 M
  159. *                                                                            *
  160. * PARAMETERS:                                                                M
  161. *   Center:   Of circle to be created.                                       M
  162. *   Radius:   Of circle to be created.                                       M
  163. *                                                                            *
  164. * RETURN VALUE:                                                              M
  165. *   CagdCrvStruct *:   A circle centered at Center and radius Radius that is M
  166. *                      parallel to the XY plane represented as a rational    M
  167. *                      quadratic Bspline curve.                              M
  168. *                                                                            *
  169. * KEYWORDS:                                                                  M
  170. *   BspCrvCreateCircle, circle                                               M
  171. *****************************************************************************/
  172. CagdCrvStruct *BspCrvCreateCircle(CagdPtStruct *Center, CagdRType Radius)
  173. {
  174.     CagdPtStruct OriginPt;
  175.     CagdCrvStruct
  176.     *Circle = BspCrvCreateUnitCircle();
  177.  
  178.     /* Do it in two stages: 1. scale, 2. translate */
  179.     OriginPt.Pt[0] = OriginPt.Pt[1] = OriginPt.Pt[2] = 0.0;
  180.     CagdCrvTransform(Circle, OriginPt.Pt, Radius);
  181.     CagdCrvTransform(Circle, Center -> Pt, 1.0);
  182.  
  183.     return Circle;
  184. }
  185.  
  186. /*****************************************************************************
  187. * DESCRIPTION:                                                               M
  188. * Approximates a unit circle as a cubic polynomial Bspline curve.         M
  189. *   Construct a circle as four 90 degrees arcs of polynomial cubic Bezier    M
  190. * segments using predefined constants.                         M
  191. *   See Faux & Pratt "Computational Geometry for Design and Manufacturing"   M
  192. * for a polynomial approximation to a circle.                                M
  193. *                                                                            *
  194. * PARAMETERS:                                                                M
  195. *   None                                                                     M
  196. *                                                                            *
  197. * RETURN VALUE:                                                              M
  198. *   CagdCrvStruct *: A cubic polynomial Bspline curve approximating a unit   M
  199. *                    circle                                                  M
  200. *                                                                            *
  201. * KEYWORDS:                                                                  M
  202. *   BspCrvCreateUnitPCircle, circle                                          M
  203. *****************************************************************************/
  204. CagdCrvStruct *BspCrvCreateUnitPCircle(void)
  205. {
  206.     int i, j, Quad;
  207.     CagdCrvStruct
  208.     *PCircle = BspCrvNew(UNIT_PCIRCLE_LENGTH, UNIT_PCIRCLE_ORDER,
  209.                                   CAGD_PT_E3_TYPE);
  210.     CagdRType
  211.     **Points = PCircle -> Points;
  212.  
  213.     for (i = 0; i < UNIT_PCIRCLE_LENGTH + UNIT_PCIRCLE_ORDER; i++)
  214.     PCircle -> KnotVector[i] = UnitPCircleKnots[i];
  215.  
  216.     Points[X][0] = Points[X][12] = 1.0;
  217.     Points[Y][0] = Points[Y][12] = 0.0;
  218.     Points[Z][0] = Points[Z][12] = 0.0;
  219.  
  220.     /* The Z components are identical in all circle, while the XY  */
  221.     /* components are functions of PolyApproxRotAngles:           */
  222.     for (Quad = 0, j = 1; j < 12; j++) {
  223.     CagdRType Angle, CosAngle, SinAngle;
  224.  
  225.     if (j % 3 == 0)
  226.         Quad++;
  227.     Angle = Quad * 90 + PolyApproxRotAngles[j % 3];
  228.     CosAngle = cos(DEG2RAD(Angle));
  229.     SinAngle = sin(DEG2RAD(Angle));
  230.  
  231.     if (ABS(CosAngle) > ABS(SinAngle))
  232.         CosAngle /= ABS(CosAngle);
  233.     else
  234.         SinAngle /= ABS(SinAngle);
  235.     Points[X][j] = Points[X][0] * CosAngle;
  236.     Points[Y][j] = Points[X][0] * SinAngle;
  237.     Points[Z][j] = 0.0;
  238.     }
  239.  
  240.     return PCircle;
  241. }
  242.  
  243. /*****************************************************************************
  244. * DESCRIPTION:                                                               M
  245. * Approximates a circle as a cubic polynomial Bspline curve at the specified M
  246. * position and radius.                                 M
  247. *   Construct the circle as four 90 degrees arcs of polynomial cubic Bezier  M
  248. * segments using predefined constants.                         M
  249. *   See Faux & Pratt "Computational Geometry for Design and Manufacturing"   M
  250. * for a polynomial approximation to a circle.                                M
  251. *                                                                            *
  252. * PARAMETERS:                                                                M
  253. *   Center:   Of circle to be created.                                       M
  254. *   Radius:   Of circle to be created.                                       M
  255. *                                                                            *
  256. * RETURN VALUE:                                                              M
  257. *   CagdCrvStruct *:   A circle approximation centered at Center and radius  M
  258. *                      Radius that is parallel to the XY plane represented   M
  259. *                      as a polynomial cubic Bspline curve.                  M
  260. *                                                                            *
  261. * KEYWORDS:                                                                  M
  262. *   BspCrvCreatePCircle, circle                                              M
  263. *****************************************************************************/
  264. CagdCrvStruct *BspCrvCreatePCircle(CagdPtStruct *Center, CagdRType Radius)
  265. {
  266.     CagdPtStruct OriginPt;
  267.     CagdCrvStruct
  268.     *Circle = BspCrvCreateUnitPCircle();
  269.  
  270.     /* Do it in two stages: 1. scale, 2. translate */
  271.     OriginPt.Pt[0] = OriginPt.Pt[1] = OriginPt.Pt[2] = 0.0;
  272.     CagdCrvTransform(Circle, OriginPt.Pt, Radius);
  273.     CagdCrvTransform(Circle, Center -> Pt, 1.0);
  274.  
  275.     return Circle;
  276. }
  277.